package main

import (
	"fmt"
	"math/rand"
	"sort"
)

func main() {
	fmt.Println("~~~~~~~~~~~~~~~第一题~~~~~~~~~~~~~~~")
	s1 := make([]int, 3, 4)
	s2 := append(s1, 1)
	fmt.Printf("s1:%v %p %p\n", s1, &s1, &s1[0])
	fmt.Printf("s2:%v %p %p\n", s2, &s2, &s2[0])

	fmt.Println("~~~~~~~~~~~~~~~第二题~~~~~~~~~~~~~~~")
	s3 := []int{1, 4, 9, 16, 2, 5, 10, 15}
	s4 := make([]int, 0, 7)
	var ele int
	for i := 1; i < len(s3); i++ {
		ele = s3[i-1] + s3[i]
		s4 = append(s4, ele)
	}
	fmt.Println(s4)

	fmt.Println("~~~~~~~~~~~~~~~第三题~~~~~~~~~~~~~~~")
	s5 := make([]int, 0, 100)
	for i := 0; i < 100; i++ {
		s5 = append(s5, rand.Intn(201)-100)
	}
	sort.Sort(sort.Reverse(sort.IntSlice(s5)))
	fmt.Println(s5)
	for i := 0; i < len(s5)-1; i++ {
		if s5[i] == s5[i+1] {
			for k := i; k < len(s5); k++ {
				if s5[k] != s5[k+1] {
					fmt.Printf("数字%v在%d位置开始重复,重复了%d次\n", s5[k], i, k-i)
					i = k
					break
				}
			}
		}
	}

	// 4、简述线性数据结构和哈希表优劣
	/***
	线性数据结构包括顺序表、链接表，他们都是有序序列，基于内存地址来存储数据。
	对于顺序表，基于连续的内存地址来存储数据，通过索引查找数据，时间复杂度是O(1)，数据的append时间复杂度
	也是O(1)，善于在尾部的增加和删除操作，对于数据的修改可以在数据的任何位置。在中间位置和头部插入、删除
	数据，比较耗时。在go中的顺序表有数组和切片，不过切片的底层也是数组，数组长度不可变，切片是可变的，由于
	切片底层也是引用的数组，当切片扩容时，底层数组会新建,将旧的数据copy到新的数组，然后再执行append操作。
	当cap小于256时，每次扩容会翻倍，否则，扩容后的cap为oldcap的1.25倍+192。
	对于链接表，其内存地址是无序的，但是每个元素都是有前后顺序的，链接表的结构体会保存next地址来
	使链接表保持连续性。go语言的list是双向链表，结构体不但保存next地址，还有prev地址。查找数据的时间复杂度
	是O(n)，在表头部、尾部增删数据的时间复杂度是O(1)，在表中间增加和删除数据，只需修改前后元素的结构体指针
	即可，效率较高。
	对于哈希表，是无序的，由k、v对组成一个元素，哈希表的地址是有序的。哈希表会根据key进行hash计算，生成一个
	hash值，然后根据哈希值计算出对应的内存地址来存储数据。数据的增加、删除、修改及查找指定key的时间复杂度
	是O(1)，当数据量庞大的时候，有可能会出现哈希碰撞，解决方法有开地址法和拉链法，go语言的map采用的是拉链法。
	哈希表有负载因子，是指hash表中已存储元素的数量与hash表容量之间的比率，用于衡量hash表的填充程度。当负载因子
	超过阈值时，hash表会扩容，扩容时会对已存储的元素进行重哈希再存储。
	***/

}
// 批改意见
// 1. 尝试使用自己的语言组织第一题的答案
// 2. 第三题尝试倒序输出结果的同时输出数字的重复次数
